#include "mainwindow.h"

#include "ui_mainwindow.h"
#include <qdesktopwidget.h>
#include <QMessageBox>
#include "qtq_config.h"
#include "about.h"
#include "qqdef.hpp"
#include "qqclient.hpp"
#include "group.hpp"
#include "qun.hpp"
#include <stdio.h>
#include <map>
#include "buddychat.h"
#include "db.h"
#include "debug.hpp"
#include "utf8.hpp"
#include "QSound"
extern qqclient* qq;
//extern int myqq_get_buddy_info( qqclient* qq, uint uid, char* buf, int size );
extern QString myqq_get_buddy_name( qqclient* qq, uint uid );
extern const char* mode_string( int mode );
using namespace std;
extern GroupByUIdInfoRecords gGoupedInforecords;//分组信息暂存
extern MsgQueque gMsgQueque; //消息队列
extern vector<Status> g_StatusChange;
map<int,QTreeWidgetItem *> g_GroupMap;
map<QTreeWidgetItem *,qqgroup*> g_GroupMapFinder;
map<int,QTreeWidgetItem *> g_BuddyMap;
map<int,QTreeWidgetItem *> g_QunMap;
map<QTreeWidgetItem *,int> g_GroupPresentInfo;
bool soundState = true;
Q_DECLARE_METATYPE(qqbuddy*);
Q_DECLARE_METATYPE(qqqun*);

MainWindow::MainWindow(QWidget *parent) :
    QDialog(parent)
{
    setupUi(this);
    QString qqHeaderFile = RC_PREFIX "QQTheme/QQHead.png";
    this->lblFace->setPixmap(QPixmap( qqHeaderFile ));
    this->treeBuddy->setIconSize(QSize(40,40));
    //this->treeBuddy->setFirstColumnSpanned()
    this->treeBuddy->setRootIsDecorated(false);

    //this->treeBuddy->set >setRootIsDecorated(false);
    this->treeGroup->setVisible(false);;
    this->treeBuddy->setVisible(true);
    connect(this,SIGNAL(StatusChanged()),SLOT(OnStatusChanged()));
    connect(treeGroup,SIGNAL(itemClicked(QTreeWidgetItem *, int)),SLOT(onQunClick(QTreeWidgetItem *, int)));
    connect(treeGroup,SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),SLOT(onQunDBClick(QTreeWidgetItem *, int)));

    connect(treeBuddy,SIGNAL(itemClicked(QTreeWidgetItem *, int)),SLOT(onBuddyClick(QTreeWidgetItem *, int)));
    connect(treeBuddy,SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),SLOT(onBuddyDBClick(QTreeWidgetItem *, int)));
    connect(treeBuddy,SIGNAL(itemExpanded(QTreeWidgetItem *)),SLOT(onBuddyExpanded(QTreeWidgetItem *)));
    connect(treeBuddy,SIGNAL(itemCollapsed(QTreeWidgetItem *)),SLOT(onBuddyCollapsed(QTreeWidgetItem *)));

    connect(btnAbout, SIGNAL(clicked()), this, SLOT(showAbout()));
    connect(btnExit, SIGNAL(clicked()), this,SLOT(OnClose()));
    connect(btnSound,SIGNAL(clicked()), this, SLOT(toggleSound()));
    connect(btnMinimum, SIGNAL(clicked()), this, SLOT(onMinimumSizeButton()));

    showSets(false);

    QDesktopWidget* desktop = QApplication::desktop();
    move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2);

    connect(lblGroup, SIGNAL(Clicked(QClickedLabel*)),SLOT(onClickQunButton()));
    connect(lblBuddy, SIGNAL(Clicked(QClickedLabel*)),SLOT(onClickBuddyButton()));

    connect(lblSetting, SIGNAL(Clicked(QClickedLabel*)),SLOT(onClickSetButton()));
    connect(lblInfoTip, SIGNAL(Clicked(QClickedLabel*)),SLOT(onClickReadButton()));

    lblSetsbk->setVisible(false);

    timer = new QTimer(this);
    timer->setInterval(500);
    connect( timer, SIGNAL(timeout()), this, SLOT(timerDone()) );
    timer->start();
    connect(this, SIGNAL(NewMesgArrived()), this,  SLOT(qtqPlaySound()));
    connect(this, SIGNAL(NewSysInfoArrived()), this,  SLOT(ShowSysInfo()));
}
void MainWindow::ShowSysInfo()
{
    InfoRecords* infos = gGoupedInforecords[0];
    if(infos)
    {
        QString info;

        std::vector<STR_inforecord>::iterator it;
        for(it = infos->begin();it != infos->end(); it++)
        {
            STR_inforecord record = *it;
            info.append(record.info).append("\r\n");

        }
        gGoupedInforecords.erase(0);
        QMessageBox::information(0,QObject::tr("系统信息"),info);
        return;
    }
}
void MainWindow::qtqPlaySound()
{
    if(soundState)
    {
        #ifdef __SYMBIAN__
            QString path = QDesktopServices::storageLocation( QDesktopServices::DataLocation );
            QString sndPath = QString("%1%2").arg(path).arg("/sound/msg.wav");
        #else
            QString sndPath = QString("%1%2").arg(QCoreApplication::applicationDirPath()).arg("/sound/msg.wav");
        #endif
            QString sndFile = QString("playSound:%1").arg( sndPath );
            DBG_QS( sndFile );

        QSound::play(sndPath);
    }
}
void MainWindow::EmitMSG()
{
    emit NewMesgArrived();
}
void MainWindow::EmitSysMSG()
{
    emit NewSysInfoArrived();
}

void MainWindow::timerDone()
{
    static uint PingPong = 0;
    PingPong++;
    if(gMsgQueque.size()>0)
    {
        if(PingPong > 2)
        {
            lblInfoTip->setVisible(true);
            lblInfoTip->setPixmap(QPixmap(RC_PREFIX"QQTheme/MsgCenter2.png"));
            PingPong = 0;
        }
        else
        {
            lblInfoTip->setPixmap(QPixmap(RC_PREFIX"QQTheme/MsgCenter1.png"));
        }
    }
    else
    {
         lblInfoTip->setPixmap(QPixmap(RC_PREFIX"QQTheme/MsgCenter1.png"));
         lblInfoTip->setVisible(false);
    }
}

void MainWindow::onBuddyDBClick(QTreeWidgetItem *item, int column)
{
    bool itemIsGroup = item->parent() == NULL;
    if(!itemIsGroup)
    {
        if(!buddychatWin)
        {
            buddychatWin = new BuddyChat();
        }
        QVariant var = item->data(0,Qt::UserRole);
        qqbuddy *b = var.value<qqbuddy*>();
#ifdef __SYMBIAN32__
    buddychatWin->showFullScreen();
    buddychatWin->raise();
#elif defined(Q_WS_MAEMO_5)
        buddychatWin->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
	buddychatWin->showFullScreen();
        buddychatWin->raise();
#else
    buddychatWin->show();
#endif

    buddychatWin->ActiveTabByUid(b->number,QObject::tr(b->nickname),0);
    }
}
void MainWindow::onQunClick(QTreeWidgetItem *item, int column)
{
    static QTreeWidgetItem * lastSelectItem2 = NULL;
    if(item->isSelected() && lastSelectItem2 == item)
    {
        if(!buddychatWin)
        {
            buddychatWin = new BuddyChat();
        }
        QVariant var = item->data(0,Qt::UserRole);
        qqqun *q = var.value<qqqun*>();
        #ifdef __SYMBIAN32__
            buddychatWin->showFullScreen();
            buddychatWin->raise();
		#elif defined(Q_WS_MAEMO_5)
                        buddychatWin->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
			buddychatWin->showFullScreen();
			buddychatWin->raise();			
        #else
            buddychatWin->show();
        #endif

        buddychatWin->ActiveTabByUid(q->number,QObject::tr(q->name),1);
    }
    else
    {
        lastSelectItem2 = item;
    }
}

void MainWindow::onQunDBClick(QTreeWidgetItem *item, int column)
{
    if(!buddychatWin)
    {
        buddychatWin = new BuddyChat();
    }
    QVariant var = item->data(0,Qt::UserRole);
    qqqun *q = var.value<qqqun*>();
#ifdef __SYMBIAN32__
buddychatWin->showFullScreen();
buddychatWin->raise();
#elif defined(Q_WS_MAEMO_5)
        buddychatWin->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
	buddychatWin->showFullScreen();
    buddychatWin->raise();	
#else
buddychatWin->show();
#endif

    buddychatWin->ActiveTabByUid(q->number,QObject::tr(q->name),1);
}

void MainWindow::onBuddyClick(QTreeWidgetItem *item, int column)
{
    static QTreeWidgetItem * lastSelectItem = NULL;
    bool itemIsGroup = item->parent() == NULL;
    if(!itemIsGroup) // click on buddy
    {
        if(item->isSelected() && lastSelectItem == item)
        {
            if(!buddychatWin)
            {
                buddychatWin = new BuddyChat();
            }
            QVariant var = item->data(0,Qt::UserRole);
            qqbuddy *b = var.value<qqbuddy*>();
            #ifdef __SYMBIAN32__
                buddychatWin->showFullScreen();
                buddychatWin->raise();
			#elif defined(Q_WS_MAEMO_5)
                                buddychatWin->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
				buddychatWin->showFullScreen();
				buddychatWin->raise();					
            #else
                buddychatWin->show();
            #endif

				buddychatWin->ActiveTabByUid(b->number,QObject::trUtf8(b->nickname),0);
        }
        else
        {
            lastSelectItem = item;
        }
    }
    else// click on group
    {

        item->setExpanded(!item->isExpanded());

    }
}
void MainWindow::onBuddyExpanded(QTreeWidgetItem *item)
{
    item->setIcon(0, QIcon(RC_PREFIX "QQTheme/PowerTreeFlag2.png"));
}
void MainWindow::onBuddyCollapsed(QTreeWidgetItem *item)
{
    item->setIcon(0, QIcon(RC_PREFIX "QQTheme/PowerTreeFlag1.png"));
}
void MainWindow::toggleSound()
{
    soundState = !soundState;
    if(!soundState)
        initMainSettingWidget(btnSound,QPixmap(RC_PREFIX "QQTheme/MainSettings1.png"));
    else
        initMainSettingWidget(btnSound,QPixmap(RC_PREFIX "QQTheme/MainSettings2.png"));
}

void MainWindow::onLoginSuccess()
{
#ifdef __SYMBIAN32__
    this->showFullScreen();
    this->raise();
#elif defined(Q_WS_MAEMO_5)
    this->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
    this->showFullScreen();
    this->raise();
#else
    this->show();
#endif

    initOwner();
    retriveGroup();
    retriveBuddy();
    retriveQun();
}
void MainWindow::initOwner()//初始化主人
{
    uint uid = qq->number;
    qqbuddy *b = buddy_get( qq, uid, 0 );

    if( b == NULL ){
            QString errorInfo = QObject::tr("获取 %s 的信息失败");
			QString uidstr=myqq_get_buddy_name( qq, uid );
            errorInfo.arg(uidstr);
            QMessageBox::critical(0,"critical",errorInfo);
    }else{
            //QMessageBox::information(0,"info",buf);
            this->lblNickname->setText( QObject::tr(b->nickname) );
            #ifndef NO_BUDDY_DETAIL_INFO
            this->lblSign->setText( QObject::tr( b->signature ) );
            #else
            this->lblSign->setText( "N/A" );
            #endif
            if(b->face >0)
            {
                QString number = QString("%1").arg(b->face + 1);
                QString status = b->status == QQ_OFFLINE ? "Offline" : "Online" ;
                QString faceFile = QString(RC_PREFIX "%1/QQTheme/QQHead_").arg(status) + status + QString("/QQHead") + status  + number + QString(".PNG");
                this->lblFace->setPixmap(QPixmap(faceFile));
            }
    }
}

void MainWindow::retriveGroup()//初始化分组
{
    QTreeWidgetItem *group = new QTreeWidgetItem();
    group->setIcon(0, QIcon(RC_PREFIX "QQTheme/PowerTreeFlag1.png"));
    group->setText(0, QObject::tr("我的好友"));
    this->treeBuddy->addTopLevelItem(group);
    g_GroupMap[0] = group;
	qq->group_list_lock.lock();    
    for(size_t i=0; i<qq->group_list.size(); i++ ){
            qqgroup* g = (qqgroup*)qq->group_list[i];
            //sprintf( temp, "%s%u\t%s^@", temp, g->number, g->name );
            QTreeWidgetItem *group = new QTreeWidgetItem();
            group->setIcon(0, QIcon(RC_PREFIX "QQTheme/PowerTreeFlag1.png"));
            //group->setCheckState(0, Qt::Checked);
			group->setText(0, g->name);
            this->treeBuddy->addTopLevelItem(group);
            g_GroupMap[g->number] = group;
            g_GroupMapFinder[group] = g;
    }
    qq->group_list_lock.unlock();
}
void MainWindow::OnStatusChanged()
{
    //db &infoDB = db::GetInstance();
    //infoDB.lockMemory();
    while(g_StatusChange.size()>0)
    {
        Status &s = g_StatusChange.back();
        qqbuddy* b = s.b;
        int lastStatus = s.laststatus;
        this->removeBuddy(b,lastStatus);
        this->addBuddy(b,lastStatus);
        int gId = b->gid;
        qqgroup* g = (qqgroup*)group_get(qq,gId,0);

        caleGroupTitle(g);
        if(b->status == QQ_ONLINE && lastStatus != QQ_ONLINE )
        {
            if(soundState)
            {
                #ifdef __SYMBIAN__
                    QString path = QDesktopServices::storageLocation( QDesktopServices::DataLocation );
                    QString sndPath = QString("%1%2").arg(path).arg("/sound/global.wav");
                #else
                    QString sndPath = QString("%1%2").arg(QCoreApplication::applicationDirPath()).arg("/sound/global.wav");
                #endif
                    QString sndFile = QString("playSound:%1").arg( sndPath );
                    DBG_QS( sndFile );

                QSound::play(sndPath);
            }
        }
        g_StatusChange.pop_back();
    }
    //infoDB.unlockMemeory();
}

void MainWindow::ChangeStatus(qqbuddy* b,int lastStatus)
{
    Status s;
    s.b = b;
    s.laststatus = lastStatus;

    db &infoDB = db::GetInstance();
    infoDB.mutex_status.lock();
    g_StatusChange.push_back(s);
    infoDB.mutex_status.unlock();
    emit StatusChanged();

}
void MainWindow::removeBuddy(qqbuddy* b,int lastStatus)
{
    int gId = b->gid;
    int number = b->number;
    //int face = b->face;
    QTreeWidgetItem *group = g_GroupMap[gId];
    QTreeWidgetItem *child = g_BuddyMap[number];
    if(group == NULL || child == NULL)
        return;
    group->removeChild(child);
    g_BuddyMap.erase(number);
    if(b->status == QQ_OFFLINE && lastStatus != QQ_OFFLINE )
    {
        if(g_GroupPresentInfo.find(group) != g_GroupPresentInfo.end())
        {
            g_GroupPresentInfo[group] --;
        }
    }
}

void MainWindow::addBuddy(qqbuddy* b,int lastStatus)
{
    int gId = b->gid;
    int face = b->face;
    QTreeWidgetItem *group = g_GroupMap[gId];
    if(group != NULL)
    {
        QVariant var;
        var.setValue (b);
        QTreeWidgetItem *child = new QTreeWidgetItem();
        g_BuddyMap[b->number] = child;
        child->setData(0,Qt::UserRole,var);
        QString faceFile;
        if(face>0 && face < 172)
        {
            QString number = QString("%1").arg(b->face);
            QString status = b->status == QQ_OFFLINE ? "Offline" : "Online" ;
            faceFile = QString(RC_PREFIX "QQHead_%1/QQTheme/QQHead_%2/QQHead_%3%4.png").arg( status,status,status,number);
            //this->lblFace->setPixmap(QPixmap(faceFile));
            child->setIcon(0, QIcon(faceFile));
        }
        else
        {
            if(b->status == QQ_OFFLINE)
            {
                child->setIcon(0, QIcon(RC_PREFIX "/QQHead_Offline/QQTheme/QQHead_Offline/QQHead_Offline8.png"));
            }
            else
            {
                child->setIcon(0, QIcon(RC_PREFIX "/QQHead_Online/QQTheme/QQHead_Online/QQHead_Online8.png"));
            }
        }

        //group->setCheckState(0, Qt::Checked);
        if(strlen(b->nickname)<=0)
        {
            QString number = QString("%1").arg(b->number);//num为int型值,10表示进制
            child->setText(0, number);
        }
        else
        {
            child->setText(0, QString::fromUtf8(b->nickname));
        }
        if(b->status == QQ_OFFLINE )
        {
            child->setToolTip(0,QString(mode_string(b->status)) +  QString( face>0 ? faceFile : RC_PREFIX "QQTheme/QQHead.PNG"));
            group->addChild(child);

        }
        else
        {
            child->setToolTip(0,QString("QQ_ONLINE,") +  QString( face>0 ? faceFile : RC_PREFIX "QQTheme/QQHead.PNG"));
            group->insertChild(0,child);
            if(g_GroupPresentInfo.find(group) == g_GroupPresentInfo.end())
            {
                g_GroupPresentInfo[group] = 1;
            }
            else
            {
                if(lastStatus == QQ_OFFLINE ||  lastStatus == 0)
                {
                    g_GroupPresentInfo[group] ++;
                }
            }
        }
//            len = sprintf( buf, "%s%-8d%-16d%-16s%-16.64s\n", buf, ln ++, b->number,
//                    mode_string( (int) b->status ), util_escape( b->nickname ) );
        //if( len + 80 > size ) break;
    }
}

void MainWindow::retriveBuddy()//初始化好友
{


    //memset(&onlineCounts,qq->buddy_list.count,sizeof(int));
    //memset(&offlineCounts,qq->buddy_list.count,sizeof(int));
	QMutexLocker myql_(&qq->buddy_list_lock);	
    for( size_t i=0; i<qq->buddy_list.size(); i++ )
    {
            qqbuddy * b = (qqbuddy*)qq->buddy_list[i];
            //if( online && b->status == QQ_OFFLINE ) continue;
            this->addBuddy(b);
    }
    for (int i=0;i<this->treeBuddy->topLevelItemCount();i++)
    {
        QTreeWidgetItem *group = this->treeBuddy->topLevelItem(i);
        qqgroup* g = g_GroupMapFinder[group];
        caleGroupTitle(g);
    }
    //return len;
}
void MainWindow::caleGroupTitle(qqgroup* g) //计算组在线情况
{

    QTreeWidgetItem *group;
    if(g)
        group = g_GroupMap[g->number];
    else
    {
        group = g_GroupMap[0];
    }
    //XXX:add by scm
    if(group==NULL) return;
    int onlineCount = g_GroupPresentInfo[group];
    int allCount = group->childCount();
    QString title;
    if(g)
    {
        title = QString("%1 [%2/%3]").arg(g->name).arg(onlineCount).arg(allCount);
    }
    else
    {
        title = QString("我的好友 [%1/%2]").arg(onlineCount).arg(allCount);
    }
    group->setText(0,title);

}

void MainWindow::retriveQun()//初始化群
{
    qq->qun_list_lock.lock();
    //avoid editing the array
    for(size_t i=0; i<qq->qun_list.size(); i++ )
    {
            qqqun * q = (qqqun *)qq->qun_list[i];
            QTreeWidgetItem *qun = new QTreeWidgetItem();
            qun->setIcon(0, QIcon(RC_PREFIX "QQTheme/PowerTreeFlag1.png"));
            //group->setCheckState(0, Qt::Checked);
			qun->setText(0, QString::fromUtf8(q->name));
            this->treeGroup->addTopLevelItem(qun);
            g_QunMap[q->number] = qun;

            QVariant var;
            var.setValue (q);

            qun->setData(0,Qt::UserRole,var);

            //len = sprintf( buf, "%s%-8d%-16d%-16d%-16.64s\n", buf, ln ++, q->number,
            //        q->ext_number, util_escape( q->name ) );
            //if( len + 80 > size ) break;
    }
    qq->qun_list_lock.unlock();
}

void MainWindow::initMainSettingWidget(QPushButton* button,QPixmap pixMap)
{
    //connect(btnAbout, SIGNAL(clicked()),SLOT(showAbout()));
    button->setFlat(true);
    button->setText("");
    button->resize(60,60);
    button->setIconSize(QSize(48,40));
    button->setIcon(pixMap) ;
}
void MainWindow::OnClose()
{
    if (QMessageBox::question(
            this,
            tr("退出程序吗？"),
            tr("是否退出DreamQQ 2010 ?"),
            QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::Yes)

    this->close();

}
void MainWindow::showAbout()
{
    About *a = new About();
#if defined(__SYMBIAN32__)
    a->showFullScreen();
    a->raise();
#elif defined(Q_WS_MAEMO_5)
        a->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
	a->showFullScreen();
    a->raise();
#else
    a->show();
#endif
    QApplication::setActiveWindow(a);
}
void MainWindow::onMinimumSizeButton()
{
    static bool bFullScreen = true;
    this->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
    if(bFullScreen)
    {
        this->showMaximized();
        bFullScreen = false;
    }
    else
    {
        this->showFullScreen();
        bFullScreen = true;
    }
}

void MainWindow::onClickQunButton()
{
   treeBuddy->setVisible(false);
    treeGroup->setVisible(true);
}
void MainWindow::onClickBuddyButton()
{
   treeBuddy->setVisible(true);
   treeGroup->setVisible(false);
}
void MainWindow::onClickSetButton()
{
    static bool setsVisible = false;
    setsVisible = !setsVisible;
    showSets(setsVisible);
}
void MainWindow::onClickReadButton()
{
    db &infoDB = db::GetInstance();
    infoDB.mutex_chat.lock();
    if(gMsgQueque.size()<=0)
    {
        infoDB.mutex_chat.unlock();
        return;
    }
    infoqueque q = gMsgQueque.top();
    uint friendId = q.number;
    uint type = q.type;

    QString nickname = QString(q.number);
    if(type == 0)
    {
        qqbuddy* b = buddy_get( qq, friendId, 0 );
        if(b)
            nickname = QObject::tr( b->nickname );
    }
    else if(type == 1)
    {
        qqqun* q= qun_get(qq,friendId,0);
        if(q)
            nickname = QObject::tr( q->name );
    }
    gMsgQueque.pop();
    infoDB.mutex_chat.unlock();

    if(friendId>0)
    {
        if(!buddychatWin)
        {
            buddychatWin = new BuddyChat(this);
        }
    #ifdef __SYMBIAN32__
        buddychatWin->showFullScreen();
        buddychatWin->raise();
	#elif defined(Q_WS_MAEMO_5)
                buddychatWin->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
		buddychatWin->showFullScreen();
		buddychatWin->raise();			
    #else
        buddychatWin->show();
    #endif
        buddychatWin->ActiveTabByUid(friendId,nickname,type);
    }
}
void MainWindow::showSets(bool isVisible)
{
//    static bool setsVisible = false;
//    setsVisible = !setsVisible;

    btnAbout->setVisible(isVisible);
    btnAdd->setVisible(isVisible);
    btnExit->setVisible(isVisible);

    btnFind->setVisible(isVisible);
    btnGroup->setVisible(isVisible);
    btnSound->setVisible(isVisible);
    btnTheme->setVisible(isVisible);
    btnUpdate->setVisible(isVisible);

    lblSetsbk->setVisible(isVisible);

}

void MainWindow::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        retranslateUi(this);
        break;
    default:
        break;
    }
}
